<?php

class MultiLevel extends Zend_Db_Table_Abstract
{
//    protected $_name;
//    protected $_primary;
    protected $_prefix_table = "";
    protected $db;


    /**
     * Insert node to another node
     *
     * @param array $data.
     *        if data is null => insert as root
     * @return  lastInsertId if success
     */
    public function insert(array $data, $parentField = false) {

        if (!is_array($data))
        return false;

        // root has not parent
        if(!@$data['parent']) {
            // add root to data
            $data['left'] = 1;
            $data['right'] = 2;
            if(true == $parentField){
                $data['parent'] = null;
            }
            $new_id = parent::insert($data);
            return $new_id;
        }

        $parent_id = -1;
        @$parent_id = $data['parent'];
        if ($parent_id < 0)
        return false;

        $table_name = $this->_name;
        $primary_key = $this->_primary;
        if($primary_key)
        $primary_key = $primary_key[1];

        // kiem tra parent co ton tai hay khong
        $select = Zend_Db_Table_Abstract::select();
        $select->where("$primary_key = '$parent_id'");

        $parent_record = $this->fetchRow($select);

        if (!$parent_record)
        return false;

        // lay right de update value cho record moi
        $right_parent = $parent_record->right;

        $new_left = $right_parent;
        $new_right = $new_left + 1;

        // update array data
        $data['left'] = $new_left;
        $data['right'] = $new_right;

        $new_id = parent::insert($data);

        // update right + 2 voi nhung records co right > new_right va khong phai new row
        $sql = "UPDATE $table_name SET `right` = `right` + 2 WHERE `right` >= $new_left AND `$primary_key` != $new_id";
        $this->_db->query($sql);

        // update left + 2 voi nhung records co left > new_left
        $sql = "UPDATE $table_name SET `left` = `left` + 2 WHERE `left` > $new_left";
        $this->_db->query($sql);

        $this->reloadCacheOfCategory();
        return $new_id;
    }

    /**
     * Delete node from tree
     *
     * @param int id.
     * @return  boolean
     */
    public function delete($id) {
        //        $db = Zend_Registry::get('db');
        if ($id < 0)
        return false;

        $table_name = $this->_name;
        $primary_key = $this->_primary;
        if($primary_key)
        $primary_key = $primary_key[1];

        $select = $select = Zend_Db_Table_Abstract::select();
        $select->where("$primary_key = $id");

        $delete_record = $this->fetchRow($select);

        if(!$delete_record)
        return false;

        $left_delete = $delete_record->left;
        $right_delete = $delete_record->right;

        // delete node and children
        $num_delete = parent::delete("`left` >= '$left_delete' AND `left` <= '$right_delete'");

        // update right - 2 * num_delete voi nhung records co right > right_delete
        $sql = "UPDATE $table_name SET `right` = `right` - " . (2 * $num_delete) . " WHERE `right` > $right_delete";
        $this->_db->query($sql);

        // update left - 2 * num_delete voi nhung records co left > left_delete
        $sql = "UPDATE $table_name SET `left` = `left` - " . (2 * $num_delete) . " WHERE `left` > $left_delete";
        $this->_db->query($sql);

        $this->reloadCacheOfCategory();
        return true;
    }

    public function move($current_node_id, $new_parent_id) {

        // this node has not changed parent
        if ($current_node_id == $new_parent_id)
        return true;

        $table_name = $this->_name;
        $primary_key = $this->_primary;
        if($primary_key)
        $primary_key = $primary_key[1];

        // get parent node and current node
        $select = Zend_Db_Table_Abstract::select();
        $select->from(array('node' => $this->_name), array('left', 'right', $primary_key, "COUNT(parent.$primary_key) -1 AS depth" ))
        ->from(array('parent' => $this->_name), array())
        ->where("node.`$primary_key` in ($current_node_id, $new_parent_id)")
        ->where("node.left BETWEEN parent.left AND parent.right")
        ->group("node.$primary_key")
        ->order("node.$primary_key ASC")
        ;


        $nodes = $this->fetchAll($select)->toArray();

        // check 2 nodes in tree
        if (count($nodes) != 2)
        return false;

        if ($nodes[0][$primary_key] == $current_node_id) {
            $current_node = $nodes[0];
            $parent_node = $nodes[1];
        } else {
            $current_node = $nodes[1];
            $parent_node = $nodes[0];
        }

        $left_current = $current_node['left'];
        $right_current = $current_node['right'];
        $left_parent = $parent_node['left'];
        $right_parent = $parent_node['right'];

        //        echo "<br>LC: " . $left_current = $current_node['left'];
        //        echo "<br>RC: " . $right_current = $current_node['right'];
        //        echo "<br>LP: " . $left_parent = $parent_node['left'];
        //        echo "<br>RP: " . $right_parent = $parent_node['right'];
        // End get parent node and current node

        // check move root
        if ($left_current == 1)
        return false;

        // check do not need to move:
        if (($current_node['depth'] == $parent_node['depth'] + 1) && ($left_current > $left_parent && $left_current < $right_parent))
        return true;




        // get all children
        $select = Zend_Db_Table_Abstract::select();
        $select
        ->from($table_name, array($primary_key))
        ->where("`left` between $left_current AND $right_current")
        ;
        $delete_tree = $this->fetchAll($select)->toArray();

        $id_move = array();

        foreach ($delete_tree as $value) {
            $id_move[] = $value[$primary_key];
        }

        // check move node to child node
        if (in_array($new_parent_id, $id_move))
        return false;

        $str_id_delete = implode(",", $id_move);

        $num_nodes = count($delete_tree);

        // update left va right.
        if ($left_current < $left_parent) {
            // move from left to right
            $sql = "UPDATE $table_name SET `left` = `left` - " . (2 * $num_nodes) . " WHERE `left` > $left_current AND `left` <= $right_parent AND $primary_key not in ($str_id_delete)";
            //            $sql = "UPDATE $table_name SET `left` = `left` - " . (2 * $num_nodes) . " WHERE `left` > $left_current AND `left` <= $left_parent AND $primary_key not in ($str_id_delete)";
            $this->_db->query($sql);

            $sql = "UPDATE $table_name SET `right` = `right` - " . (2 * $num_nodes) . " WHERE `right` > $right_current AND `right` < $right_parent AND $primary_key not in ($str_id_delete)";
            $this->_db->query($sql);

            // update nodes has removed
            $delta = $left_current - $right_parent;

            $sql = "UPDATE $table_name SET `left` = `left` - $delta - " . (2*$num_nodes) . ", `right` = `right` - $delta - " . (2*$num_nodes) . " WHERE $primary_key in ($str_id_delete)";
            $this->_db->query($sql);
        } else {
            if($left_current > $right_parent) {
                // move from right to left
                $sql = "UPDATE $table_name SET `left` = `left` + " . (2 * $num_nodes) . " WHERE `left` > $right_parent AND `left` < $left_current AND $primary_key not in ($str_id_delete)";
                $this->_db->query($sql);

                $sql = "UPDATE $table_name SET `right` = `right` + " . (2 * $num_nodes) . " WHERE `right` >= $right_parent AND `right` < $right_current AND $primary_key not in ($str_id_delete)";
                $this->_db->query($sql);

                // update nodes has removed
                $delta = $left_current - $right_parent;

                $sql = "UPDATE $table_name SET `left` = `left` - $delta , `right` = `right` - $delta WHERE $primary_key in ($str_id_delete)";
                $this->_db->query($sql);
            } else {
                //                echo "Move inside";
                // move from child to super parent

                /**
                 * UPDATE VALUE
                 *
                 * Tree move: L,R = L,R - (delta - 1)
                 *
                 * All left node of tree move
                 *      L = L + delta  (all left node)
                 *      R = R + delta ( node has condition Lp < R < Lc)
                 *
                 */
                $delta = $left_current - $left_parent;

                //                die;
                //update tree want to move
                $sql = "UPDATE $table_name SET `left` = `left` - " . ($delta - 1) . ", `right` = `right` - " . ($delta - 1) . "  WHERE $primary_key in ($str_id_delete)";
                $this->_db->query($sql);

                //update left node of current

                //update left value
                $sql = "UPDATE $table_name SET `left` = `left` + " . (2 * $num_nodes) . " WHERE `left` > $left_parent AND `left` < $left_current AND $primary_key not in ($str_id_delete)";
                $this->_db->query($sql);

                //update right value
                $sql = "UPDATE $table_name SET `right` = `right` + " . (2 * $num_nodes) . " WHERE `right` > $left_parent AND `right` < $left_current AND $primary_key not in ($str_id_delete)";
                $this->_db->query($sql);
            }
        }

        try {
            // move node to new location
            $sql = "UPDATE $table_name SET `parent` = $new_parent_id WHERE `$primary_key` = $current_node_id";
            $this->_db->query($sql);
        } catch (Exception $ex){}

        $this->reloadCacheOfCategory();
    }



    /**
     * Get tree of node
     *
     * @param int $node_id
     * @param string $order
     * @param boolean $drop_to_leaf If false, you can drop tree to leaf.
     */
    public function getTreeOfNode($node_id = null, $order = "left ASC", $drop_to_leaf = false, $langCode = null) {

        $table_name = $this->_name;
//        $primary_key = $this->_primary;
//        if($primary_key)
//        $primary_key = $primary_key[1];
        $primary_key = $this->getPrimaryKey();

        if (!$order) $order = "left ASC";

        if($node_id) {
            $select = Zend_Db_Table_Abstract::select();
            $select
            ->where("$primary_key = $node_id")
            ;

            $current = $this->fetchRow($select);

            if (!$current) {
                return false;
            }

            $left_current  = $current->left;
            $right_current = $current->right;

            // get tree
            //            $select = $this->_db->select()
            //                ->where("`left` between $left_current AND $right_current")
            //                ->order($order)
            //            ;
            $order = "node." . $order;

            $select = Zend_Db_Table_Abstract::select();
            $select
            ->from(array('node' => $this->_name), array('left', 'admin_title','right', $primary_key, "COUNT(parent.$primary_key) -1 AS depth" ))
            ->from(array('parent' => $this->_name), array())
            //->where("node.`$primary_key` in (?)", array($current_node_id, $new_parent_id))
            ->where("node.`left` between $left_current AND $right_current")
            ->where("node.left BETWEEN parent.left AND parent.right")
            ->group("node.$primary_key")
            ->order($order)
            ;


            //            $allCategory = $this->getRecords("`left` between $left_current AND $right_current", $order);
        } else {
            // get tree
            //            $select = $this->_db->select()
            //                ->order($order)
            //            ;
            $order = "node." . $order;

            $select = Zend_Db_Table_Abstract::select();
            $select
            ->from(array('node' => $this->_name), array('left','admin_title', 'right','short_description', 'description', $primary_key, "COUNT(parent.$primary_key) -1 AS depth" ))
            ->from(array('parent' => $this->_name), array())
            ->where("node.left BETWEEN parent.left AND parent.right")
            ->group("node.$primary_key")
            ->order($order)
            ;
        }

        //        echo $langCode;
        if($langCode) {
            $select->setIntegrityCheck(false)
            ->from(array('cat' => $table_name))
            ->joinLeft( array( 'catlang' => DB_PREFIX . $this->_prefix_field . "content"), "cat.{$this->_prefix_field}category_id = catlang.{$this->_prefix_field}category_id", array('title', 'friendly_url', 'description'))
            ->where("catlang.language_code = '$langCode'")
            ;
        }

//        echo $select;die;
        //        echo $select;
        $allCategory = $this->fetchAll($select);

        if ($allCategory) {
            $allCategory = $allCategory->toArray();
        } else {
            return null;
        }

        //        echo "<pre>";
        //        print_r($allCategory);
        //        echo "</pre>";

        $root = true;
        $tree = array();


        foreach ($allCategory as $node) {

            $parent[$node['depth']] = $node["$primary_key"];
            // create variable for current node
            $new_node_name = "node" . $node[$primary_key];
            $new_node = $node;
            $new_node["id"] = $node[$primary_key];
            $new_node["text"] = (@$node['title'])?$node['title']:$node['admin_title'];
            /*$new_node = array(
                "id" => $node[$primary_key],
            //                "uiProvider" => 'col',
            //                "text" => $node['admin_title'],
                "text" => (@$node['title'])?$node['title']:$node['admin_title'],
            );*/

            if ($drop_to_leaf == 'true') {
                // use bellow line for tree has not leaf
                // this option use for drag and drop to leaf
                $new_node["children"] = array();
            } else {
                // use 3 lines bellow for tree has leaf
                if($node['left'] == $node['right'] - 1)
                $new_node["leaf"] = true;
                else $new_node["children"] = array();
            }

            $$new_node_name = $new_node;
            //end create current node

            if(($node['left'] != 1) && ($node[$primary_key] != $node_id)){
                // update parent node
                $parent_name = "node".$parent[$node['depth'] - 1];
                $parent_node = $$parent_name;

                // use & for update
                $parent_node['children'][] = &$$new_node_name;
                $$parent_name = $parent_node;
            }

            if ($root) {
                // use & for update
                $tree = &$$new_node_name;
                $root = false;
            }

        }

        return $tree;
    }

    /**
     * Get tree of node
     *
     * @param int $node_id
     * @param string $order
     * @param boolean $drop_to_leaf If false, you can drop tree to leaf.
     */
    public function getTreeOfNodeMultiColumns($node_id = null, $order = "left ASC", $drop_to_leaf = false, $langCode = null) {

        $table_name = $this->_name;
        $primary_key = $this->_primary;
        if($primary_key)
        $primary_key = $primary_key[1];

        if (!$order) $order = "left ASC";

        if($node_id) {
            $select = Zend_Db_Table_Abstract::select();
            $select
            ->where("$primary_key = $node_id")
            ;

            $current = $this->fetchRow($select);

            if (!$current) {
                return false;
            }

            $left_current  = $current->left;
            $right_current = $current->right;

            // get tree
            $select = Zend_Db_Table_Abstract::select();
            $select
            ->where("`left` between $left_current AND $right_current")
            ->order($order)
            ;
            //            $allCategory = $this->getRecords("`left` between $left_current AND $right_current", $order);
        } else {
            // get tree
            $select = Zend_Db_Table_Abstract::select();
            $select
            ->order($order)
            ;
        }

        if($langCode) {
            $select->setIntegrityCheck(false)
            ->from(array('cat' => $table_name))
            ->joinLeft( array( 'catlang' => DB_PREFIX . $this->_prefix_field . "content"), "cat.{$this->_prefix_field}category_id = catlang.{$this->_prefix_field}category_id", array('title', 'friendly_url', 'description'))
            ->where("catlang.language_code = ")
            ;
        }

        $allCategory = $this->fetchAll($select);

        if ($allCategory) {
            $allCategory = $allCategory->toArray();
        } else {
            return null;
        }

        //        echo "<pre>";
        //        print_r($allCategory);
        //        echo "</pre>";

        $root = true;
        $tree = array();


        foreach ($allCategory as $node) {

            // create variable for current node
            $new_node_name = "node" . $node[$primary_key];
            $new_node = array(
                "id" => $node[$primary_key],
                "uiProvider" => 'col',
                "demo" => @$node['demo'],
                "images" => "<span onclick=\"listImage(" . $node[$primary_key] . ");\">
                                		<img src='" . APP_BASE_URL ."userfile/cpanel/icons/delete16x16.png'/>
                                	</span>",
                "items" => "<span onclick=\"listItems(" . $node[$primary_key] . ");\">
                                		<img src='" . APP_BASE_URL ."userfile/cpanel/icons/delete16x16.png'/>
                                	</span>",
                "text" => (@$node['title'])?$node['title']:$node['admin_title'],
    			"iconEditDel" => "<span onclick=\"deleteCategoryConfirm(" . $node[$primary_key] . ", '" . ((@$node['title'])?$node['title']:$node['admin_title']) . "' );\">
                                		<img src='" . APP_BASE_URL ."userfile/cpanel/icons/delete16x16.png'/>
                                	</span>
                                	<span onclick='editCategory(" . $node[$primary_key] . ");'>
                                		<img src='" . APP_BASE_URL ."userfile/cpanel/icons/edit16x16.png'/>
                                	</span>"
                                	);

                                	if ($drop_to_leaf == 'true') {
                                	    // use bellow line for tree has not leaf
                                	    // this option use for drag and drop to leaf
                                	    $new_node["children"] = array();
                                	} else {
                                	    // use 3 lines bellow for tree has leaf
                                	    if($node['left'] == $node['right'] - 1)
                                	    $new_node["leaf"] = true;
                                	    else $new_node["children"] = array();
                                	}

                                	$$new_node_name = $new_node;
                                	//end create current node

                                	if(($node['parent'] != null) && ($node[$primary_key] != $node_id)){
                                	    // update parent node
                                	    $parent_name = "node".$node['parent'];
                                	    $parent_node = $$parent_name;

                                	    // use & for update
                                	    $parent_node['children'][] = &$$new_node_name;
                                	    $$parent_name = $parent_node;
                                	}

                                	if ($root) {
                                	    // use & for update
                                	    $tree = &$$new_node_name;
                                	    $root = false;
                                	}

        }

        return $tree;
    }

    /**
     * Get all parent by id
     *
     * @param <int> $id
     * @return <false> if fail, <array> if success. Array will have structure as:
     * Array
     (
     [prefix_field_category_id] => 1
     [parent] =>
     [left] => 1
     [right] => 18
     [chidren] => Array
     (
     [prefix_field_category_id] => 2
     [parent] => 1
     [left] => 2
     [right] => 11
     [chidren] => Array
     (
     [prefix_field_category_id] => 5
     [parent] => 2
     [left] => 7
     [right] => 10
     [chidren] => Array
     (
     [prefix_field_category_id] => 9
     [parent] => 5
     [left] => 8
     [right] => 9
     )

     )

     )

     )
     *
     */
    public function getParentsByIdPrepareJson($id)
    {
        $primaryKey = $this->_primary[1];
        $select = Zend_Db_Table_Abstract::select();
        $select->where($primaryKey . " = ?", $id);

        $data = $this->fetchRow($select);
        if (! $data) {
            return false;
        }

        $select = Zend_Db_Table_Abstract::select();
        $select->where("`left` <= ?", $data->left)
        ->where("`right` >= ?", $data->right)
        ->order("left ASC")
        ;
        $array = $this->fetchAll($select);
        if (! $array) {
            return false;
        }
        $array = $array->toArray();
        //        echo"<pre>";print_r($array);die;
        //Pasre array to tree
        $result = array();
        $count = count($array);
        for ($i = $count - 1; $i >= 0; $i--) {
            $result = '';
            $result = $array[$i];
            if ($i != $count - 1) {
                $result['chidren'] = $tmp;
            }
            $tmp = $result;
        }

        echo"<pre>";print_r($result);die;
    }

    /**
     * Enter description here...
     *
     * @param unknown_type $id
     * @return unknown
     */
    public function getPath($id)
    {
        $table_name = $this->_name;
        $primaryKey = $this->_primary;
        if($primaryKey)
        $primaryKey = $primaryKey[1];

        $select = Zend_Db_Table_Abstract::select();
        $select->where($primaryKey . " = '$id'");

        //        echo $select;die;
        $data = $this->fetchRow($select);
        if (! $data) {
            return array();
        }

        $select = Zend_Db_Table_Abstract::select();
        $select->where("`left` <= '{$data->left}'")
        ->where("`right` >= '{$data->right}'")
        ->order("left ASC")
        ;
        $array = $this->fetchAll($select);
        //        if (! $array) {
        //            return array();
        //        }
        //        $array = $array->toArray();

        return $array;
    }

    /**
     * Get all parent  as array associated with Json by id
     *
     * @param <int> $id
     * @return <false> if fail, <array> if success. Array will have structure as:
     * Array
     (
     [prefix_field_category_id] => 1
     [parent] =>
     [left] => 1
     [right] => 18
     [prefix_field_category_content_id] => 5
     [title] => Test1
     [friendly_url] => test/test1
     [description] => Test 1 o day na`
     [language_code] => vi
     [id] => 1
     [leaf] => false
     [chidren] => Array
     (
     [prefix_field_category_id] => 2
     [parent] => 1
     [left] => 2
     [right] => 11
     [prefix_field_category_content_id] => 4
     [title] => Test2
     [friendly_url] => test/test2
     [description] => Test nua, test hoai
     [language_code] => vi
     [id] => 2
     [leaf] => false
     [chidren] => Array
     (
     [prefix_field_category_id] => 5
     [parent] => 2
     [left] => 7
     [right] => 10
     [prefix_field_category_content_id] => 3
     [title] => Test5
     [friendly_url] => test/test5
     [description] => Cai gi cung duoc
     [language_code] => vi
     [id] => 5
     [leaf] => false
     [chidren] => Array
     (
     [prefix_field_category_id] => 9
     [parent] => 5
     [left] => 8
     [right] => 9
     [prefix_field_category_content_id] => 1
     [title] => Test
     [friendly_url] => test/test
     [description] => Test thu coi
     [language_code] => vi
     [id] => 9
     [leaf] => true
     )

     )

     )

     )
     *
     *
     */
    public function getParentsAsJsonById($id)
    {
        $primaryKey = $this->_primary[1];
        $select = Zend_Db_Table_Abstract::select();
        $select->where($primaryKey . " = ?", $id);

        $data = $this->fetchRow($select);
        if (! $data) {
            return false;
        }

        $select = Zend_Db_Table_Abstract::select();
        $select->setIntegrityCheck(false)
        ->from(array( 'tbl' => $this->_name))
        ->join(array( 'a' => DB_PREFIX . $this->_prefix_field . 'content'), "a.{$this->_prefix_field}category_id = tbl.{$this->_prefix_field}category_id")
        ->where("tbl.`left` <= ?", $data->left)
        ->where("tbl.`right` >= ?", $data->right)
        ->order("tbl.left ASC")
        ;
        $array = $this->fetchAll($select);

        if (! $array) {
            return false;
        }
        $array = $array->toArray();
        //        echo"<pre>";print_r($array);die;
        //Pasre array to tree
        $result = array();
        $count = count($array);
        for ($i = $count - 1; $i >= 0; $i--) {
            $result = '';
            $result = $array[$i];
            $result['id'] = $result[$this->_prefix_field . 'category_id'];
            $result['leaf'] = 'false';
            if ($i != $count - 1) {
                $result['chidren'] = $tmp;
            } else {
                $result['leaf'] = 'true';
            }
            $tmp = $result;
        }

        echo"<pre>";print_r($result);die;
    }

    /**
     * Enter description here...
     *
     * @param unknown_type $id
     * @return unknown
     */
    //    public function getPathById($id)
    //    {
    //        $table_name = $this->_name;
    //        $primaryKey = $this->_primary;
    //        if($primaryKey)
    //            $primaryKey = $primaryKey[1];
    //
    //        $select = Zend_Db_Table_Abstract::select();
    //        $select->where($primaryKey . " = ?", $id);
    //
    ////        echo $select;die;
    //        $data = $this->fetchRow($select);
    //        if (! $data) {
    //            return array();
    //        }
    //
    //        $select = Zend_Db_Table_Abstract::select();
    //        $select->where("`left` <= ?", $data->left)
    //               ->where("`right` >= ?", $data->right)
    //               ->order("left ASC")
    //              ;
    //        $array = $this->fetchAll($select);
    //        if (! $array) {
    //            return array();
    //        }
    //        $array = $array->toArray();
    //
    //        return $array;
    //    }
    /**
     * Enter description here...
     *
     * @param unknown_type $id
     * @param unknown_type $langCode
     * @return get multiLevel with language
     */
    public function getPathById($id, $langCode = null)
    {
        $table_name = $this->_name;
        $primaryKey = $this->_primary;
        if($primaryKey)
        $primaryKey = $primaryKey[1];

        $select = Zend_Db_Table_Abstract::select();
        $select->where($primaryKey . " = ?", $id);

        //        echo $select;die;
        $data = $this->fetchRow($select);
        if (! $data) {
            return array();
        }

        $select = Zend_Db_Table_Abstract::select();
        if($langCode)
        {
            $select->setIntegrityCheck(false);
            $select->from(array('cat' => $table_name));
            $select->joinLeft(array('catlang' => DB_PREFIX."category_content"), "cat.category_id = catlang.category_id AND catlang.language_code = '{$langCode}'", array('title','friendly_url','description'));
        }
        $select->where("`left` <= ?", $data->left);
        $select->where("`right` >= ?", $data->right);
        $select->order("left ASC");

        $array = $this->fetchAll($select);

        if (! $array) {
            return array();
        }
        $array = $array->toArray();

        return $array;
    }

    public function getAllChildByCatId($node_id = null, $order = "left ASC", $langCode = null) {

        $table_name = $this->_name;
        $primary_key = $this->_primary;
        if($primary_key)
        $primary_key = $primary_key[1];

        if (!$order) $order = "left ASC";

        if($node_id) {
            $select = Zend_Db_Table_Abstract::select();
            $select
            ->where("$primary_key = $node_id")
            ;

            $current = $this->fetchRow($select);

            if (!$current) {
                return false;
            }

            $left_current  = $current->left;
            $right_current = $current->right;

            // get tree
            $select = Zend_Db_Table_Abstract::select();
            $select
            ->where("`left` between $left_current AND $right_current")
            ->order($order)
            ;
            //            $allCategory = $this->getRecords("`left` between $left_current AND $right_current", $order);
        } else {
            // get tree
            $select = Zend_Db_Table_Abstract::select();
            $select
            ->order($order)
            ;
        }

        if($langCode) {
            $select->setIntegrityCheck(false)
            ->from(array('cat' => $table_name))
            ->joinLeft( array( 'catlang' => DB_PREFIX . $this->_prefix_field . "content"), "cat.{$this->_prefix_field}category_id = catlang.{$this->_prefix_field}category_id", array('title', 'friendly_url', 'description'))
            ->where("catlang.language_code = ")
            ;
        }

        $allCategory = $this->fetchAll($select);

        if ($allCategory) {
            $allCategory = $allCategory->toArray();
            return $allCategory;
        } else {
            return null;
        }
        return null;
    }

    public function getRecords($order = 'node.left ASC')
    {
        $table_name = $this->_name;
        $primary_key = $this->_primary;
        if(is_array($primary_key))
        $primary_key = $primary_key[1];

        $select = Zend_Db_Table_Abstract::select();
        //        ->setIntegrityCheck(false)
        $select
        ->from(array('node' => $this->_name))
        ->join(array('parent'=> $this->_name), "node.left BETWEEN parent.left AND parent.right", array('level' => 'COUNT(parent.left) -1'))
        ->group("node.$primary_key")
        ->order($order);

        //$data = $this->fetchAll($select);
        $stmt = $select->query();
        $data = $stmt->fetchAll();

        return $data;
    }

    public function getRecordsAsFolder($order = 'node.left ASC', $getRoot = false)
    {
        $table_name = $this->_name;
        $primary_key = $this->_primary;
        if(is_array($primary_key))
            $primary_key = $primary_key[1];

        $select = Zend_Db_Table_Abstract::select();
        //        ->setIntegrityCheck(false)
        $select
        ->from(array('node' => $this->_name), array('category_id', "CONCAT( REPEAT('..|..', COUNT(parent.admin_title) - 1), node.admin_title) AS admin_title
        "))
        ->join(array('parent'=> $this->_name), "node.left BETWEEN parent.left AND parent.right", array('level' => 'COUNT(parent.left) -1'))
        ->group("node.$primary_key")
        ->order($order);

//        if (!$getRoot)
//            $select->where("node.`left` !=1");

        //$data = $this->fetchAll($select);
        $stmt = $select->query();
        $data = $stmt->fetchAll();

        return $data;
    }

    public function getRoot()
    {
        $table_name = $this->_name;
        $primary_key = $this->_primary;
        if($primary_key)
        $primary_key = $primary_key[1];

        $select = Zend_Db_Table_Abstract::select();
        //        ->setIntegrityCheck(false)
        $select->where("`left` = 1");

        //        $stmt = $select->query();
        //        $data = $stmt->fetch();
        $data = $this->fetchRow();

        return $data;
    }

    public function getCategoryById($id)
    {
        $table_name = $this->_name;
        $primary_key = $this->_primary;
        if($primary_key)
        $primary_key = $primary_key[1];

        $select = Zend_Db_Table_Abstract::select();
        //        ->setIntegrityCheck(false)
        if ($id > 0)
        $select->where("`$primary_key` = '$id'");

        //        $stmt = $select->query();
        //        $data = $stmt->fetch();
        $data = $this->fetchRow($select);

        return $data;
    }

    /**
     * cac array long nhau
     * @return array
     */
    public function reloadCacheOfCategory() {

        $frontendName = "Core";
        $backendName = "File";
        $frontendOptions = array(
                'lifetime' => null, // null to forever
                'automatic_serialization' => true
        );
        $backendOptions = array(
                 'cache_dir' => "cache/" // thư mục chứa các file cache
        );

        try {
            $cache = Zend_Cache::factory($frontendName, $backendName, $frontendOptions, $backendOptions);
        } catch (Exception $ex) {
            echo "Please create folder cache";
            return;
        }

        $allRecords = $this->getRecords();
        $categories = array();
        foreach($allRecords as $category):
        $categories[$category['category_id']] = $category;
        endforeach;
        $cache->save($categories, "allcategories");

        return $categories;
    }
    /**
     * cac array long nhau
     * @return array
     */
    public function getCacheOfCategory() {

        $frontendName = "Core";
        $backendName = "File";
        $frontendOptions = array(
                'lifetime' => null, // null to forever
                'automatic_serialization' => true
        );
        $backendOptions = array(
                 'cache_dir' => "cache/" // thư mục chứa các file cache
        );

        try {
            $cache = Zend_Cache::factory($frontendName, $backendName, $frontendOptions, $backendOptions);
        } catch (Exception $ex) {
            echo "Please create folder cache";
            return;
        }

//        $categories = $cache->load('allcategories');
        $categories = null;

        if (!$categories) {
            $allRecords = $this->getRecords();
//            print_r($allRecords);die;
            $categories = array();
            foreach($allRecords as $category):
                $category['full_friendly_url'] = $category['friendly_url'];
                if ($category['parent']) {
                    $categories[$category['parent']]['children'][] = $category['category_id'];
                    $category['full_friendly_url'] = $categories[$category['parent']]['full_friendly_url'] . "/" . $category['friendly_url'];
                }
                $categories[$category['category_id']] = $category;
                //                $categories[$category['parent']]['full_friendly_url'] = $category['category_id'];
            endforeach;
            $cache->save($categories, "allcategories");
        }

        return $categories;
    }

    /**
     * Get breadcumb of category id
     * @param int $categoryID
     * @param array $categoryCache // array cache of category -> getCacheOfCategory
     * @return String
     */
    public function getStringBreadcumb($categoryID, $showRoot = false, $categoryCache = null) {
        if(is_array($categoryCache)) {
            $cache = $categoryCache;
        } else {
            $cache = $this->getCacheOfCategory();
        }

        $allID = array_keys($cache);

        if(in_array($categoryID, $allID)) {
            $parentID = $cache[$categoryID]['parent'];
            if ($parentID) {
                $parentCategory = $cache[$parentID];
                $leftParent = $parentCategory['left'];
                if ($leftParent != 1){
                    return $this->getStringBreadcumb($parentID, $showRoot, $cache) . ">>" . $cache[$categoryID]['admin_title'];
                } else {
                    if ($showRoot) {
                        return $this->getStringBreadcumb($parentID, $showRoot, $cache) . ">>" . $cache[$categoryID]['admin_title'];
                    } else {
                        return $cache[$categoryID]['admin_title'];
                    }
                }
            } else {
                return $cache[$categoryID]['admin_title'];
            }
        }
        return null;
    }

    /**
     * Get array path of breadcumb
     * @param $categoryID
     * @param $showRoot
     * @param $categoryCache
     * @return unknown_type
     */

    public function getArrayBreadcumb($categoryID, $showRoot = false, $categoryCache = null) {
        if(is_array($categoryCache)) {
            $cache = $categoryCache;
        } else {
            $cache = $this->getCacheOfCategory();
        }
        $allID = array_keys($cache);

        if(in_array($categoryID, $allID)) {
            $currID = $categoryID;
            $result = array();
            while($currID != null) {
                $currCategory = $cache[$currID];
                if (($currCategory['left'] == 1) && !$showRoot) {
                    //$result[$currCategory['level']] = $currCategory;
                } else {
                    $result[$currCategory['level']] = $currCategory;
                }
                $currID = $currCategory['parent'];
            }
            return $result;
        }
        return null;
    }

    public function getAllCategoryAsFolder() {
        $allRecords = $this->getCacheOfCategory();
        $categories = array();
        foreach($allRecords as $category):
            $categories[$category['category_id']] = $category;
        endforeach;
        return $categories;
    }

    /**
     * Lay con truc tiep
     * @param $id
     * @return unknown_type
     */
    public function getChild($id) {
        $table_name = $this->_name;
        $primary_key = $this->_primary;
        if($primary_key)
        $primary_key = $primary_key[1];

        $select = Zend_Db_Table_Abstract::select();
        //        ->setIntegrityCheck(false)
        $select->where("`parent` = '$id'");

        //        $stmt = $select->query();
        //        $data = $stmt->fetch();
        $data = $this->fetchAll($select);

        return $data;
    }

    /**
     * Lay con truc tiep
     * @param $id
     * @return unknown_type
     */
    public function getMainMenu() {
        $table_name = $this->_name;
//        $primary_key = $this->_primary;
//        if($primary_key)
//        $primary_key = $primary_key[1];

        $select = Zend_Db_Table_Abstract::select();
        //        ->setIntegrityCheck(false)
        $select->where("`main_menu` = '1'");

        //        $stmt = $select->query();
        //        $data = $stmt->fetch();
        $data = $this->fetchAll($select);

        return $data;
    }

    public function getCacheOfAll() {
//        $primaryKey = $this->_primary;
//        if(is_array($primary_key))
//            $primary_key = $primary_key[1];

        //$select = Zend_Db_Table_Abstract::select();

        $allRecords = $this->getCacheOfCategory();
        //        echo"<pre>";print_r($array);die;
        //Pasre array to tree
        $result = array();
        $count = count($allRecords);
        for ($i = $count - 1; $i >= 1; $i--) {
            $result = '';
            $result = $allRecords[$i];
            $result['id'] = $result[$this->_prefix_field . 'category_id'];
            $result['leaf'] = 'false';
            if ($i != $count - 1) {
                $result['chidren'] = $tmp;
            } else {
                $result['leaf'] = 'true';
            }
            $tmp = $result;
        }

//        echo"<pre>";print_r($result);die;
        return $result;
    }

    /**
     * Get all tree of node
     *
     * @param int $node_id
     * @param string $order
     * @param boolean $drop_to_leaf If false, you can drop tree to leaf.
     */
    public function getAllTree($langCode = null) {

        $table_name = $this->_name;

        $primary_key = $this->_primary;
        if(is_array($primary_key)) {
            $primary_key = $primary_key[1];
        }
        $primary_key = $this->getPrimaryKey();

        $order = "node.left ASC";

        $select = Zend_Db_Table_Abstract::select();
        $select
            ->from(array('node' => $this->_name),
                array('left','admin_title', 'right','short_description', 'description', 'friendly_url',
                'parent', $primary_key, "COUNT(parent.$primary_key) -1 AS depth" ))
            ->from(array('parent' => $this->_name), array())
            ->where("node.`left` BETWEEN parent.`left` AND parent.`right`")
            ->group("node.$primary_key")
            ->order($order);

        if($langCode) {
            $select->setIntegrityCheck(false)
            ->from(array('cat' => $table_name))
            ->joinLeft( array( 'catlang' => DB_PREFIX . $this->_prefix_field . "content"), "cat.{$this->_prefix_field}category_id = catlang.{$this->_prefix_field}category_id", array('title', 'friendly_url', 'description'))
            ->where("catlang.language_code = '$langCode'")
            ;
        }

        $allCategory = $this->fetchAll($select);

        if ($allCategory) {
            $allCategory = $allCategory->toArray();
        } else {
            return null;
        }

//        $tree = array();
//        foreach($allCategory as $category):
////            $nodeid = $category[$primary_key];
//            $category['children'] = array();
//            $$nodeid = $category;
//
////            if ($category['parent'])
//        endforeach;
//
//        return $tree;
//
        $root = true;
        $tree = array();

        foreach ($allCategory as $node) {

            $parent[$node['depth']] = $node["$primary_key"];
            // create variable for current node
            $new_node_name = "node" . $node[$primary_key];
            $new_node = $node;
            $new_node["id"] = $node[$primary_key];
            $new_node["text"] = (@$node['title'])?$node['title']:$node['admin_title'];
            /*$new_node = array(
                "id" => $node[$primary_key],
            //                "uiProvider" => 'col',
            //                "text" => $node['admin_title'],
                "text" => (@$node['title'])?$node['title']:$node['admin_title'],
            );*/

            if($node['left'] == $node['right'] - 1)
            $new_node["leaf"] = true;
            else $new_node["children"] = array();

//            if ($drop_to_leaf == 'true') {
//                // use bellow line for tree has not leaf
//                // this option use for drag and drop to leaf
//                $new_node["children"] = array();
//            } else {
//                // use 3 lines bellow for tree has leaf
//                if($node['left'] == $node['right'] - 1)
//                $new_node["leaf"] = true;
//                else $new_node["children"] = array();
//            }

            $$new_node_name = $new_node;
            $tmpNode = $$new_node_name;
            //end create current node

//            if(($node['left'] != 1) && ($node[$primary_key] != $node_id)){
            if($node['left'] != 1){
                // update parent node
                $parent_name = "node".$parent[$node['depth'] - 1];
                $parent_node = $$parent_name;

                // use & for update
                $parent_node['children'][$tmpNode['friendly_url']] = &$$new_node_name;
                $$parent_name = $parent_node;
            }

            if ($root) {
                // use & for update
                $tree = &$$new_node_name;
                $root = false;
            }

        }

        return $tree;
    }
}
?>
